class GruntFactory(object):
    def __init__(self):
        self.counter = 0
    def NewGrunt(self):
        return Grunt(self)
    def NextTurn(self):
        self.counter += 1
    
class Attribute(object):
    """Basically a timeline of values"""
    def __init__(self, default=0):
        self.timeline = [default]
    def __getitem__(self, index):
        assert index >= 0, "Don't use negative indices--it's error-prone. Compute the turn explicitly."    
        ## Don't extend on read
        if(index >= len(self.timeline)):
            return self.timeline[-1]
        else:
            return self.timeline[index]
    def __setitem__(self, index, val):
        ## Don't use negative indices--it's error-prone. Compute the turn explicitly.
        assert index >= 0, "Don't use negative indices--it's error-prone. Compute the turn explicitly."
        self.extend(index)
        self.timeline[index] = val
    def extend(self, index):
        """If indexed beyond the end, extend"""
        if(index >= len(self.timeline)):
            tl = self.timeline
            last = tl[-1]
            for i in range(len(tl), index+1):
                tl.append(last)
        
    
def __makeGruntAttribute(attribname):
    privateName = '_' + attribname
    def create(self): 
        setattr(self, privateName, Attribute())
    def get(self):
        return getattr(self, privateName)[self.factory.counter]
    def set(self, val):
        getattr(self, privateName).__setitem__(self.factory.counter, val)
    def print_(x): print x
    setattr(Grunt, attribname, property(get, set))
    Grunt.attribs.append(create)

class Grunt(object):
    def __init__(self, factory):
        self.factory = factory
        self.icon = None
        self.team = None
        self.coords = None
        self.name = None
        self.effects = []
        self.mind = None
        for attribCreate in self.attribs:
            attribCreate(self)
    def infotext(self):
        return """%s\nST: %s\nDX: %s\nHT: %s\nIQ: %s\nHP: %s""" % (self.name, self.ST, self.DX, self.HT, self.IQ, self.HP)

    attribs = []
    
__makeGruntAttribute("ST")
__makeGruntAttribute("DX")
__makeGruntAttribute("HT")
__makeGruntAttribute("IQ")
__makeGruntAttribute("HP")

class Team(object):
    def __init__(self):
        self.color = None
        self.grunts = []
    def add(self, grunt):
        self.grunts.append(grunt)
        grunt.team = self
    
if __name__ == "__main__":
    a = Attribute(66)
    a[3] = 77
    assert a[1] == 66
    assert a[3] == 77
    fac = GruntFactory()
    g = fac.NewGrunt()
    g.HP = 10
    g.ST = 12
    g.DX = 12
    g.IQ = 12
    g.HT = 12
    # check that changing the present doesn't affect the past
    fac.NextTurn()
    g.HP = 11
    assert g.HP == 11
    assert g._HP[1] == 11
    assert g._HP[0] == 10
    assert g.HT == 12
    print 'grunt.py smoke tests pass'